package com.altran.mirth.migration.v211.utils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;

import com.altran.mirth.migration.v211.MigrationComment;

/**
 * Project :  Mirth
 * Author :   Altran
 * URL :      http://Mirth.eryos.fr
 *
 * Copyright (C) 2011 - Altran 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */

public class Logger {
	
	private final static String LINE_RETURN = MigrationComment.LINE_RETURN;

	File inputFile;
	File outputFile;
	
	BufferedWriter defaultWriter;
	HashMap<String, BufferedWriter> listOfLogs = new HashMap<String, BufferedWriter>();
	
	private static Logger logger;
	
		private Logger(){
		
	}
	
	public static Logger getInstance(){
		
		if ( logger == null )
			logger = new Logger();
		
		return logger;
	}

	private static String convertLineToReadableLine(String line){
		return line.replaceAll("&quot;", "'").replaceAll("&apos;", "'");
	}
	
	private String getTimeStamp(){
		
		Calendar cal = Calendar.getInstance();
		
		return (cal.get(Calendar.MONTH)+1)+"/"+cal.get(Calendar.DAY_OF_MONTH)+"/"+cal.get(Calendar.YEAR)+" - "+cal.get(Calendar.HOUR_OF_DAY)+":"+cal.get(Calendar.MINUTE)+":"+cal.get(Calendar.SECOND);
	}
	
	private static final String LOG_PATH = "Mirth_Config/Logs/";
	
	public void initLog(){
		String name = "Mirth_Migration";
		File logFile = new File(LOG_PATH+name+".log");
		try {
			defaultWriter = new BufferedWriter(new FileWriter(logFile));
			listOfLogs.put(name, defaultWriter);

			initLog(defaultWriter, name);
		}catch(IOException e){
			e.printStackTrace();
		}
	}

	public void finalizeLogs(){
		try {
			
			for ( BufferedWriter writer : logger.listOfLogs.values() )
				writer.close();

		} catch (IOException e) {
			e.printStackTrace();
		}		

	}
		
	private void initLog(BufferedWriter writer, String title){
		try {
			writer.write("-- **************************************** --"+LINE_RETURN);
			writer.write("-- "+ title + " --"+LINE_RETURN);
			writer.write("-- "+ getTimeStamp()+ " --"+LINE_RETURN);
			writer.write("-- **************************************** --"+LINE_RETURN);
			writer.newLine();
			writer.newLine();
						
			writer.write("-- **************************************** --"+LINE_RETURN);
			writer.write("Original File : "+inputFile.getAbsolutePath()+LINE_RETURN);
			writer.write("Migrated File : "+outputFile.getAbsolutePath()+LINE_RETURN);
			writer.write("-- **************************************** --"+LINE_RETURN);
			writer.newLine();
			writer.newLine();
			
			writer.write("-- **************************************** --"+LINE_RETURN);
			writer.write(" ***** [BATCH_TAG] ***** "+LINE_RETURN);
			writer.write("(Original Line Number)	Old version of the code"+LINE_RETURN);
			writer.write("(New Line Number)	New version of the code"+LINE_RETURN);
			writer.write("-- **************************************** --"+LINE_RETURN);
			writer.newLine();
			writer.newLine();
			
			writer.write("-- **************************************** --"+LINE_RETURN);
			for ( String line : MigrationComment.getAllTags()){
				writer.write(line + LINE_RETURN);				
			}
			writer.write("-- **************************************** --"+LINE_RETURN);
			writer.newLine();
			writer.newLine();
			writer.flush();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}	
	}
	
	public void log(String logs){
		try {
			
			// ************************** Results **************************
			System.out.println(logs);
			
			defaultWriter.write(logs);
			defaultWriter.newLine();
			defaultWriter.flush();
						
		} catch (Exception e) {
			e.printStackTrace();
		}		

	}
	
	public void logChange(int oldLineNumber, int newLineNumber, String oldLine, String newLine, String comment, String tag, String channelName){
		
		System.out.println(tag+" - "+comment+" - "+oldLineNumber+"/"+newLineNumber);
		
		if ( logger.defaultWriter == null ){
			logger.initLog();
		}
		
		logChange(logger.defaultWriter, oldLineNumber, newLineNumber, oldLine, newLine, comment, tag, channelName);

		try {
			
			if ( ! logger.listOfLogs.containsKey(channelName) ){
				BufferedWriter channelWriter = new BufferedWriter(new FileWriter(new File(LOG_PATH+channelName+".log")));
				logger.listOfLogs.put(channelName, channelWriter);
				logger.initLog(channelWriter, channelName);
			}
		
			logChange(logger.listOfLogs.get(channelName), oldLineNumber, newLineNumber, oldLine, newLine, comment, tag, channelName);

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void logChange(BufferedWriter writer, int oldLineNumber, int newLineNumber, String oldLine, String newLine, String comment, String tag, String channelName){
		try {
			
			writer.write(" ***** "+tag+" ***** "+channelName+" ***** "+LINE_RETURN);
			writer.write("("+oldLineNumber+")	"+convertLineToReadableLine(oldLine.trim())+""+LINE_RETURN);
			writer.write("("+newLineNumber+")	"+convertLineToReadableLine(newLine.trim())+""+LINE_RETURN);
			writer.newLine();
			writer.flush();
			
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	
	/**
	 * @param inputFile the inputFile to set
	 */
	public void setInputFile(File inputFile) {
		this.inputFile = inputFile;
	}

	/**
	 * @param outputFile the outputFile to set
	 */
	public void setOutputFile(File outputFile) {
		this.outputFile = outputFile;
	}


}
